
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)

set(CUCC_COMPILER nvcc)
if(DEFINED ENV{CUCC_PATH})
  set(CUCC_COMPILER cucc)
endif()

set(CMAKE_LINKER $ENV{CUDA_PATH}/bin/${CUCC_COMPILER})
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

# message("CMAKE_CURRENT_SOURCE_DIR:" ${CMAKE_CURRENT_SOURCE_DIR})
# message("CMAKE_SOURCE_DIR:" ${CMAKE_SOURCE_DIR})

if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
  set(CMAKE_LINKER $ENV{CUDA_PATH}/bin/${CUCC_COMPILER} PARENT_SCOPE)
  set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" PARENT_SCOPE)
  set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" PARENT_SCOPE)
endif()

# set(CMAKE_LINKER $ENV{CUDA_PATH}/bin/nvcc CACHE STRING "Path to the CUDA linker")
# set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" CACHE STRING "CMake's linker command for CUDA")
# set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER>  <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"  CACHE STRING "CMake's linker command for CUDA")

set (CUDA_INCLUDE_DIRS $ENV{CUDA_PATH}/include $ENV{MACA_PATH}/include $ENV{MACA_PATH}/include/mcr)

set(CMAKE_CUDA_COMPILER_LIST ${CUCC_COMPILER})
set(CMAKE_CUDA_COMPILER  $ENV{CUDA_PATH}/bin/${CUCC_COMPILER})
set(CMAKE_LINKER ${CMAKE_CUDA_COMPILER})
set(CMAKE_CUDA_ARCHITECTURES 70;75;80)
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
list(APPEND CMAKE_CUDA_COMPILER_ID_VENDORS NVIDIA Clang)
set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \\(R\\) Cuda compiler driver")
set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_Clang "(clang version)")
set(_CUDA_NVCC_EXECUTABLE "${CMAKE_CUDA_COMPILER}")
set(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT $ENV{CUDA_PATH})
set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT $ENV{CUDA_PATH})
set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT $ENV{CUDA_PATH})
set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT 11.6.0)


set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER}")
set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER}")

set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v")
set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON)

set(_CMAKE_CUDA_RDC_FLAG "-rdc=true")

# Build a small source file to identify the compiler.
# if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
#   set(CMAKE_CUDA_COMPILER_ID_RUN 1)

#   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
#   include(${CMAKE_ROOT}/Modules/CUDA/architectures.cmake)
#   _cmake_find_compiler_sysroot(CUDA)
# endif()

set(_CMAKE_PROCESSING_LANGUAGE "CUDA")
include(CMakeFindBinUtils)
include(Compiler/${CMAKE_CUDA_COMPILER_ID}-FindBinUtils OPTIONAL)
unset(_CMAKE_PROCESSING_LANGUAGE)

set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES  )
set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES  )
set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES  )
set(set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "SHARED")  )


set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")


if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
  set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")

  # We do not currently detect CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES but we
  # do need to detect CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT from the compiler by
  # looking at which cudart library exists in the implicit link libraries passed
  # to the host linker.
  if(CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT MATCHES "link\\.exe [^\n]*cudart_static\\.lib")
    set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC")
  elseif(CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT MATCHES "link\\.exe [^\n]*cudart\\.lib")
    set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "SHARED")
  else()
    set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "NONE")
  endif()
  set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT
    "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")")
elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")
  string(REGEX MATCHALL "-target-cpu sm_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")

  foreach(cpu ${target_cpus})
    string(REGEX MATCH "-target-cpu sm_([0-9]+)" dont_care "${cpu}")
    list(APPEND architectures_detected "${CMAKE_MATCH_1}")
  endforeach()

  # Find target directory when crosscompiling.
  if(CMAKE_CROSSCOMPILING)
    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a")
      # Support for NVPACK
      set(_CUDA_TARGET_NAME "armv7-linux-androideabi")
    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
      set(_CUDA_TARGET_NAME "armv7-linux-gnueabihf")
    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
      if(ANDROID_ARCH_NAME STREQUAL "arm64")
        set(_CUDA_TARGET_NAME "aarch64-linux-androideabi")
      else()
        set(_CUDA_TARGET_NAME "aarch64-linux")
      endif()
    elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
      set(_CUDA_TARGET_NAME "x86_64-linux")
    endif()

    if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/${_CUDA_TARGET_NAME}")
      set(_CUDA_TARGET_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/${_CUDA_TARGET_NAME}")
    endif()
  endif()

  # If not already set we can simply use the toolkit root or it's a scattered installation.
  if(NOT _CUDA_TARGET_DIR)
    set(_CUDA_TARGET_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
  endif()

  # We can't use find_library() yet at this point, so try a few guesses.
  if(EXISTS "${_CUDA_TARGET_DIR}/lib64")
    set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib64")
  elseif(EXISTS "${_CUDA_TARGET_DIR}/lib/x64")
    set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib/x64")
  elseif(EXISTS "${_CUDA_TARGET_DIR}/lib")
    set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib")
  else()
    message(FATAL_ERROR "Unable to find _CUDA_LIBRARY_DIR based on _CUDA_TARGET_DIR=${_CUDA_TARGET_DIR}")
  endif()

  # _CUDA_TARGET_DIR always points to the directory containing the include directory.
  # On a scattered installation /usr, on a non-scattered something like /usr/local/cuda or /usr/local/cuda-10.2/targets/aarch64-linux.
  if(EXISTS "${_CUDA_TARGET_DIR}/include/cuda_runtime.h")
    set(_CUDA_INCLUDE_DIR "${_CUDA_TARGET_DIR}/include")
  else()
    message(FATAL_ERROR "Unable to find cuda_runtime.h in \"${_CUDA_TARGET_DIR}/include\" for _CUDA_INCLUDE_DIR.")
  endif()


  set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${_CUDA_INCLUDE_DIR}")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "${_CUDA_LIBRARY_DIR}")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")

  if(_nvcc_link_line)

    #prefix the line with cuda-fake-ld so that implicit link info believes it is
    #a link line
    set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}")



    if(";${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart_static(\.lib)?;]])
      set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC")
    elseif(";${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart(\.lib)?;]])
      set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "SHARED")
    else()
      set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "NONE")
    endif()
    set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT
      "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")")

    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
      "Parsed CUDA nvcc implicit link information from above output:\n${_nvcc_log}\n${log}\n\n")
  else()
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
      "Failed to parse CUDA nvcc implicit link information:\n${_nvcc_log}\n\n")
    message(FATAL_ERROR "Failed to extract nvcc implicit link line.")
  endif()
endif()


set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES_EXCLUDE
  # The CUDA runtime libraries are controlled by CMAKE_CUDA_RUNTIME_LIBRARY.
  cudart        cudart.lib
  cudart_static cudart_static.lib
  cudadevrt     cudadevrt.lib

  # Dependencies of the CUDA static runtime library on Linux hosts.
  rt
  pthread
  dl
  )

set(_SET_CMAKE_CUDA_COMPILER_SYSROOT "")

set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES  "todo")


# configure all variables set in this file
configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
  ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
  @ONLY
)

# Don't leak variables unnecessarily to user code.
unset(_CUDA_INCLUDE_DIR CACHE)
unset(_CUDA_NVCC_EXECUTABLE CACHE)
unset(_CUDA_LIBRARY_DIR)
unset(_CUDA_TARGET_DIR)
unset(_CUDA_TARGET_NAME)

unset(architectures_detected)

set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")
